//{==================================================================================================
//! @file PrimeLower.cpp
//! @date 2013-09-29
//! @mainpage  Program for finding prime numbers among the given N numbers
//! @author Kirill Shcherbatov <kshcherbatov@gmail.com>, 376 group, DCAM MIPT
//! @version 1.0
//! @note Task A, varriant 1, test 2007, MIPT
//}===================================================================================================

//****************************************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//****************************************************************************************************

//****************************************************************************************************
#define _EJC
#define PARANOIC_MODE
//****************************************************************************************************

//****************************************************************************************************
//! @def   OUT
//! @note  -Use OUT to print your text in console. It is checking _EJC declaration.
//! @note  -Only if _EJC is defined then the program prints your text.
//! @note  --You also can define _EJC in compilation command (g++ main.cpp -D _EJC)
//----------------------------------------------------------------------------------------------------
#ifdef _EJC
    #define OUT printf
#else
    #define OUT if (0) printf
#endif // _EJC
//****************************************************************************************************


//****************************************************************************************************
//! @def    VALID
//! @param  CONDITIONAL for checking
//! @param  MESSAGE for displaying if CONDITIONAL is false
//! @note   -It checks the validity of the expression.
//! @note   -Program will use OUT to display MESSAGE
//! @note   -If sended conditional is false, program will be terminated sending 1 message
//----------------------------------------------------------------------------------------------------
#ifdef  PARANOIC_MODE
    #define VALID( CONDITIONAL, MESSAGE )       \
    if (!(CONDITIONAL))                         \
    {                                           \
        OUT  ( MESSAGE );                       \
        exit ( 1 );                             \
    } // VALID in PARANOIC_MODE
#else
    #define VALID( CONDITIONAL, MESSAGE ) \
    CONDITIONAL;
#endif
//****************************************************************************************************

//****************************************************************************************************
//! @def    CHECK
//! @param  CONDITIONAL for checking
//! @param  MESSAGE for displaying if CONDITIONAL is false
//! @note   -It checks the validity of the expression.
//! @note   -Program will use OUT to display MESSAGE
//! @note   -If sended conditional is false, program will be terminated sending 1 message
//! @warning   IN RELIASE MODE IT WILL BE REMOOVED
//----------------------------------------------------------------------------------------------------
#ifdef PARANOIC_MODE
    #define CHECK( CONDITIONAL, MESSAGE )       \
    if (!(CONDITIONAL))                         \
    {                                           \
        OUT  ( MESSAGE );                       \
        exit ( 1 );                             \
    } // CHECK in PARANOIC_MODE
#else
    #define CHECK( CONDITIONAL, MESSAGE )
#endif
//****************************************************************************************************

//****************************************************************************************************
int IsPrime (unsigned int p);
//****************************************************************************************************

//****************************************************************************************************
//! @param - number of sending arguments
//! @param argv[] - arguments, include generated by OS
//! @return 0 on success
//----------------------------------------------------------------------------------------------------
int main (int, const char* argv[])
{
    OUT ("#%s (%s) %s %s:\n\n", argv[0], __FILE__, __DATE__, __TIME__);
    OUT ("#Program for finding prime numbers among the given N numbers\n\n");
    OUT ("#Enter N, the amouinnt of numbers in the sequence of input \n"
         "#N = ");

    unsigned int N = 0;

    VALID (scanf ("%u", &N) == 1,  "#Problems with inputed N. Read the instructions above & try again.\n");

    const unsigned int N_MAX = 10000;

    CHECK (N > 0, "#Inputed N is incorrect. N should be greater than 0.\n");
    CHECK (N < N_MAX, "#Inputed N is incorrect. N should be lower than 10 000.\n");;

    unsigned int *buffer = (unsigned int *)malloc (N * sizeof (unsigned int));

    CHECK(buffer != NULL, "#Sorry, there is no enough memory..\n");

    unsigned int *p = buffer;

    OUT ("#You sequence\n");

    unsigned int c = 0;
    const unsigned int C_MAX = 100000;

    for (register unsigned int i=0; i < N; i++)
    {
        VALID (scanf ("%u", &c) == 1,  "#Problems with inputed c. Read the instructions above & try again.\n");
        CHECK (N > 0, "#Inputed N is incorrect. N should be greater than 0.\n");
        CHECK (N < N_MAX, "#Inputed N is incorrect. N should be lower than 10 000.\n");;
        if (IsPrime (c) == 1) *p++=c;
    }

    if (p == buffer)
        OUT ("#The is no prime numbers in inputed amouinnt.\n");
        else
        OUT ("#The resulting sequence of prime numbers is\n");

    for (register unsigned int *i = buffer; i < p; i++)
        printf("%d ",*i);

    free (buffer);

    buffer = NULL; p = NULL;
    return 0;
}
//****************************************************************************************************

//****************************************************************************************************
//! @param p - integer for primary-checking
//! @return 1 if p is prime, else 0
//----------------------------------------------------------------------------------------------------
int IsPrime (unsigned int p)
{
    if (p == 1) return 0;
    if (p == 2) return 1;
    for (register long long unsigned int i = 2; i < sqrt (p)+1; i++ )
        if (p % i == 0) return 0;
    return 1;
}
//****************************************************************************************************
